var tgd = tgd || {};
tgd.Math = tgd.Math || {};

/* http://en.wikipedia.org/wiki/Mandelbrot_set */

tgd.Math.Mandelbrot = function (dim, callback) {
	this._dim = dim;
	this._maxIterations = 500;
	this._data = [];
	this._callback = callback;

	//loopers
	this._current = 0;
	this._stopper = Math.pow(this._dim, 2);

	for (var i = 0; i < this._dim; this._data[i++] = []);

	if (typeof tgd.Math.Mandelbrot._initialized == "undefined") {
		tgd.Math.Mandelbrot.prototype.getDimension = function() {
			return this._dim;
		}

		tgd.Math.Mandelbrot.prototype.getMaxIteration = function() {
			return this._maxIterations;
		}

		tgd.Math.Mandelbrot.prototype.getIthValue = function(idx) {
			return this._data[parseInt(idx / this._dim)][idx % this._dim];
		}

		tgd.Math.Mandelbrot.prototype.getValue = function(row, col) {
			return this._data[row][col];
		}

		tgd.Math.Mandelbrot.prototype._getIthPixel = function(idx) {
			var color = null;
			var x, y, iteration, xtemp;

			var yPix = parseInt(idx / this._dim);
			var xPix = idx % this._dim;

			x = x0 = (xPix % this._dim) / this._dim * 4 - 2;
			y = y0 = (yPix % this._dim) / this._dim * 4 - 2;
			iteration = 0;

			while (x * x + y * y <= 4 && iteration < this._maxIterations) {
				xtemp = x * x - y * y + x0;
				y = 2 * x * y + y0;
				x = xtemp;
				++iteration;
			}

			return iteration;
		}

		tgd.Math.Mandelbrot._initialized = true;
	}


	var self = this;

	var calculateRow = function() {
		if (self._current < self._stopper) {
			for (var i = 0; i < self._dim; ++i, ++self._current) {
				self._data[parseInt(self._current / self._dim)][self._current % self._dim] = self._getIthPixel(self._current);
			}
			setTimeout(calculateRow, 0);
		} else {
			self._callback();
		}
	};

	setTimeout(calculateRow, 0);
}